package routerplugin;

import com.android.SdkConstants;
import com.android.build.api.transform.DirectoryInput;
import com.android.build.api.transform.Format;
import com.android.build.api.transform.JarInput;
import com.android.build.api.transform.QualifiedContent;
import com.android.build.api.transform.Transform;
import com.android.build.api.transform.TransformException;
import com.android.build.api.transform.TransformInput;
import com.android.build.api.transform.TransformInvocation;
import com.android.build.api.transform.TransformOutputProvider;
import com.android.build.gradle.internal.pipeline.TransformManager;
import com.android.utils.FileUtils;

import org.gradle.api.Project;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Set;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

/**
 * *******************************************************
 * Author: chinadragon
 * Time: 2023/8/15 10:11
 * Name:  v4-20 - 架构-组件化
 * Overview:
 * Usage: 查看 build目录顺序 intermediates > javac -> transforms -> dex
 * *******************************************************
 */
public class JavassitTransform extends Transform {

    //java中javassist、ClassPool、CtClass、Apache CC2链学习
    //https://blog.csdn.net/qq_41874930/article/details/121273650

    //    字节码池子
    ClassPool mPool = ClassPool.getDefault();

    //    把class字节码加载到内存
    Project project;

    public JavassitTransform(Project project) {
        this.project = project;
    }


    @Override
    public String getName() {
        return "dragontransform";
    }

    @Override
    public Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS;
    }

    @Override
    public Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT;
    }

    @Override
    public boolean isIncremental() {
        return false;
    }

    @Override
    public void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
        super.transform(transformInvocation);

        //        准备工作

//   project java 工程  java--class路径  class字节码加载内存


        //查看 build目录顺序 intermediates > javac -> transforms -> dex
        //输入
        Collection<TransformInput> inputs = transformInvocation.getInputs();

        //输出
        TransformOutputProvider outputProvider = transformInvocation.getOutputProvider();


        for (TransformInput input : inputs) {

            /*
                android 四大组件是在系统目录里， 而 AppCompatActivity 是在jar 包里，


                注意：jar 不参与编译，所以jar里面的代码是不能修改的
             */
            //jar 先 copy jar，否则 apk 安装失败，找不到 AppCompatActivity
            for (JarInput jarInput : input.getJarInputs()) {
                File dest = outputProvider.getContentLocation(
                        jarInput.getName(),
                        jarInput.getContentTypes(),
                        jarInput.getScopes(),
                        Format.JAR);

                System.out.println(" === jar dest 目录 : " + dest.getAbsolutePath());
                // === jar dest 目录 : /Users/chinadragon/Desktop/android_project/TransformDemo/app/build/intermediates/transforms/dragontransform/debug/49.jar


                FileUtils.copyFile(jarInput.getFile(), dest);// 注意这里是  copyFile
            }


            //class
            for (DirectoryInput directoryInput : input.getDirectoryInputs()) {
//                String dirName = directoryInput.getName();
                File file = directoryInput.getFile();
                String preFileName = file.getAbsolutePath();
                System.out.println(" === 输入 目录 : " + preFileName);
                // /Users/chinadragon/Desktop/android_project/TransformDemo/app/build/intermediates/javac/debug/classes

                try {
                    mPool.appendClassPath(preFileName);//加载到内存，注意：这个内存是运行内存（mac、window），不是Android内存
                } catch (NotFoundException e) {
                    throw new RuntimeException(e);
                }

                //找到 classes 再 找 Router 类
                findTarget(file, preFileName);

//                //outputProvider 输出
                File dest = outputProvider.getContentLocation(
                        directoryInput.getName(),
                        directoryInput.getContentTypes(),
                        directoryInput.getScopes(),
                        Format.DIRECTORY);

                System.out.println(" === 输出 dest 目录 : " + dest.getAbsolutePath());
                // === 输出 dest 目录 : /Users/chinadragon/Desktop/android_project/TransformDemo/app/build/intermediates/transforms/dragontransform/debug/1
                FileUtils.copyDirectory(file, dest);
            }

        }

    }

    private void findTarget(File clazz, String fileName) {
//        递归寻找到 class 结尾的字节码文件    他们找出来    修改
        if (clazz.isDirectory()) {

            for (File file : clazz.listFiles()) {
                findTarget(file, fileName);
            }

        } else {
//            .class
            modify(clazz, fileName);
        }
    }

    private void modify(File clazz, String fileName) {
        String filePath = clazz.getAbsolutePath();
        if (!filePath.endsWith(SdkConstants.DOT_CLASS)) {
            return;
        }
        if (filePath.contains("R$") || filePath.contains("R.class") || filePath.contains("BuildConfig.class")) {
            return;
        }
//     . com.example.transformdemo.test.router.Router.class
        if (filePath.contains("ARouter")) {// 找了需要修改的class

            System.out.println("clazz -> " + clazz.getAbsolutePath());
            //clazz -> /Users/chinadragon/Desktop/android_project/TransformDemo/app/build/intermediates/javac/debug/classes/com/example/transformdemo/test/router/Router.class
            //fileName /Users/chinadragon/Desktop/android_project/TransformDemo/app/build/intermediates/javac/debug/classes


            String className = filePath.replace(fileName, "")
                    .replace("\\", ".")//windows系统
                    .replace("/", ".");//mac 系统
            System.out.println("处理后的 className： " + className);
            //处理后的 className： .com.example.transformdemo.test.router.Router.class

            String name = className.replace(SdkConstants.DOT_CLASS, "").substring(1);//从1开始因为前面还有.
            System.out.println("处理后的 name： " + name);
            //处理后的 name： com.example.transformdemo.test.router.Router
//
            try {

//        获得全类名   key -----》字节码对象 ctClass  ----》修改

                //目的：修改源码
                CtClass ctClass = mPool.get(name);
                CtMethod ctMethod = ctClass.getDeclaredMethod("init");
                String body = "com.example.transformdemo.ActivityUitl.putActivity(); ";
                System.out.println("插入代码前：" + name);
                ctMethod.insertBefore(body);
                System.out.println("插入代码后：" + name);
                ctClass.writeFile(fileName);
                ctClass.detach();

            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }

    }
}
